#pragma once

#include <iostream>
#include <ctime>
#include <cstdarg>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define INFO 0
#define DEBUG 1
#define WARNING 2
#define ERROR 3
#define FATAL 4

#define SCREEN 1
#define ONEFILE 2
#define MOREFILE 3

#define SIZE 1024
#define logname "log.txt"

using namespace std;

class Log
{
public:
    Log()
    :printstyle(SCREEN)
    ,path("./log/")// 默认路径是当前路径下的log文件夹
    {
        // mkdir(path.c_str(),0765);
    }

    void change(int style)
    {
        printstyle = style;
    }
    string leveltostring(int level)
    {
        switch (level)
        {
        case INFO:
            return "INFO";
        case DEBUG:
            return "DEBUG";
        case WARNING:
            return "WARNING";
        case ERROR:
            return "ERROR";
        case FATAL:
            return "FATAL";
        default:
            return "NON";
        }
    }

    void operator()(int level, const char *format, ...)
    {
        // 处理时间
        time_t now = time(nullptr);
        // 将时间戳转为本地时间
        struct tm *local_time = localtime(&now);
        char leftbuffer[SIZE];
        snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", leveltostring(level).c_str(),
                 local_time->tm_year + 1900, local_time->tm_mon + 1, local_time->tm_mday,
                 local_time->tm_hour, local_time->tm_min, local_time->tm_sec);

        // 处理可变参数
        va_list s;
        va_start(s, format);
        char rightbuffer[SIZE];
        vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
        va_end(s);

        // 将两个消息组合起来成为一个完整的日志消息
        // 默认部分+自定义部分
        char logbuffer[SIZE * 2];
        snprintf(logbuffer, sizeof(logbuffer), "%s %s", leftbuffer, rightbuffer);

        printlog(level, logbuffer);
    }
    // void logmessage(int level, const char *format, ...)
    // {
    //     // 处理时间
    //     time_t now = time(nullptr);
    //     // 将时间戳转为本地时间
    //     struct tm *local_time = localtime(&now);
    //     char leftbuffer[SIZE];
    //     snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", leveltostring(level).c_str(),
    //              local_time->tm_year + 1900, local_time->tm_mon + 1, local_time->tm_mday,
    //              local_time->tm_hour, local_time->tm_min, local_time->tm_sec);

    //     // 处理可变参数
    //     va_list s;
    //     va_start(s, format);
    //     char rightbuffer[SIZE];
    //     vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
    //     va_end(s);

    //     // 将两个消息组合起来成为一个完整的日志消息
    //     // 默认部分+自定义部分
    //     char logbuffer[SIZE * 2];
    //     snprintf(logbuffer, sizeof(logbuffer), "%s %s", leftbuffer, rightbuffer);

    //     printlog(level, logbuffer);
    // }

    void printlog(int level, const string &logbuffer) // 这里引用避免大型字符串的拷贝开销，优化性能
    {
        switch (printstyle)
        {
        case SCREEN:
            cout << logbuffer << endl;
            break;
        case ONEFILE:
            printonefile(logname, logbuffer);
            break;
        case MOREFILE:
            printmorefile(level, logbuffer);
            break;
        }
    }

    void printonefile(const string &_logname, const string &logbuffer)
    {
        string __logname = path + _logname;
        int fd = open(__logname.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666);
        if (fd < 0)
        return;
        write(fd, logbuffer.c_str(), logbuffer.size());
        close(fd);
    }

    void printmorefile(int level, const string &logbuffer)
    {
        // 思路：通过不同的文件名进行区分
        string _logname = logname;
        _logname += ".";
        _logname += leveltostring(level);
        printonefile(_logname, logbuffer);
    }

    ~Log()
    {
    }

private:
    int printstyle;
    string path;
};

Log lg;